#include <stdio.h>
#include <ctype.h>
#include <conio.h>
//E -> TE'
//E' -> +TE' | e
//T -> FT'
//T' -> *FT' | e
//F -> NUM | (E)
//FIRST(E) = {NUM, LEFTB}
//FIRST(E') = {PLUS, e}
//FIRST(T) = {NUM, LEFTB}
//FIRST(T') = {MULT, e}
//FIRST(F) = {NUM, LEFTB}
//FOLLOW(E) = {$, RIGHTB}
//FOLLOW(E') = {$, RIGHTB}
//FOLLOW(T) = {PLUS, RIGHTB, $}
//FOLLOW(T') = {PLUS, RIGHTB, $}
//FOLLOW(F) = {MULT, PLUS, RIGHTB, $}

enum TOKEN {PLUS, MULT, NUM, END, ERR, LEFTB, RIGHTB};
char lookahead;
enum TOKEN token;
int val;
int error = 0;
FILE *fp;

void lexical(FILE *fp);
int match(enum TOKEN x);
int E();
int E_();
int T();
int T_();
int F();


//return 0 if success, return 1 otherwise
int match(enum TOKEN x)
{
    if(token == x)
    {
        lexical(fp);
        return 0;
    }
    else
    {
        error = 1;
        return 1;
    }
}

//E -> TE'
int E()
{
    int num;
    switch (token)
	{
		case LEFTB:  	// FIRST(TE')={(,num}
		case NUM:
		   num=T();
		    if(token==PLUS)
			return num + E_();
			//else
           // return num - E_();

		case END:		// FOLLOW(E)={),$}
		return num;
		default:
			printf("\n Error1\n");

			break;
	}
    return 0;
}

//E_ -> +TE'|e
int E_()
{
    int num;
	switch (token)
	{
		case PLUS:	// E'-->+TE' 的情况， FIRST(E')={+,e}
			match(PLUS);
			num=T();
			if(token==PLUS)
			return num + E_();
			else
            return num;

		//case SUB:	// E'-->+TE' 的情况， FIRST(E')={+,e}
			//match(SUB);
			//num=T();
			//if(token==ADD)
			//return num- E_();
			//else
            //return num + E_();

		case RIGHTB:// E'-->e 的情况，这个时候需要处理 FOLLOW集合， FOLLOW(E')={), $}
		case END:
			return 0;
		default:
			printf("\n Error2\n");

			break;
	}
    return 0;
}

//T -> FT'
int T()
{
    int num;
    switch (token)
    {
    case LEFTB:	// FIRST(FT')={(,num}    First(T')={*,/}
    case NUM:
        num=F();
        if(token==MULT)
            return num*T_();
        else
            return num;


    default:
        printf("\n Error3\n");

        break;
    }
    return 0;
}


//T' -> *FT' | e
int T_()
{
    int num;
	switch (token)
	{
		case MULT:	// FIRST(*FT')={*,/}
			match(MULT);
			num=F();
			if(token==MULT)
			return num * T_();
			else
            return num / T_();
        //case DIV:
  			//match(DIV);
			//num=F();
			//if(token==MUL)
			//return  num / T_();
			//else
            //return num * T_();
		//case SUB:
        case PLUS:	// T'-->e 的情况，这个时候需要处理 FOLLOW集合， FOLLOW(T')={+,-,),$}
		case RIGHTB:
		case END:
			return 1;
		default:
			printf("\n Error4\n");

			break;
	}
    return 0;
}

//F -> NUM | (E)
int F()
{
    int temp;

	switch(token)
	{
		case LEFTB:	// FIRST((E))={(}
			match(LEFTB);
			temp = E();
			match(RIGHTB);
			return temp;
		case NUM:		// FIRST(num) = {num}
			temp = val;
			match(NUM);
			//printf("%d\n",temp);
			return temp;
		default:
			printf("\n Error5\n");

			break;
	}
    return 0;
}





void lexical(FILE *fp)
{

    lookahead = getc(fp);
    val = 0;

    while(lookahead == ' ' || lookahead == '\t' || lookahead == '\n')
    {
        lookahead = getc(fp);
    }

    if(isdigit(lookahead))
    {
        val = 0;
        while(isdigit(lookahead))
        {
            token = NUM;
            val = val * 10 + lookahead - '0';
            lookahead = getc(fp);
            //printf("----%c\n",lookahead);
        }
      //  printf("!!%d\n",val);
        ungetc(lookahead, fp);
        return;
    }
    else if (lookahead == '+')
    {
        token = PLUS;
        return;
    }
    else if (lookahead == '*')
    {
        token = MULT;
        return;
    }
    else if(lookahead == EOF)
    {
        token = END;
        return;
    }
    else if(lookahead == '(')
    {
        token = LEFTB;
        return;
    }
    else if(lookahead == ')')
    {
        token = RIGHTB;
        return;
    }
    else
    {
        error = 1;
        token = ERR;
        return;
    }
}

int main(int argc,char **argv)
{
    int  res = 0;
    if(argc<2)
    {

        printf("insufficient arguments");
        return 1;
    }
    fp = fopen(argv[1], "r");

    lexical(fp);
    res = E();
    if(!error)
    {
        printf("%d\n", res);
    }
    else
    {
        printf("There are errors\n");
    }

    fclose(fp);
    return 0;

}
